/*
 * 英才汇硕信息科技有限公司 拥有本软件版权 2021 并保留所有权利。
 * Copyright 2021, YCHS Information&Science Techology Co.,Ltd,
 * All right reserved.
 */
package com.ychs.lawyerback.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ychs.lawyerback.common.Constant;
import com.ychs.lawyerback.common.ResultCode;
import com.ychs.lawyerback.exception.BussinessException;
import com.ychs.lawyerback.util.JWTUtil;
import com.ychs.lawyerback.vo.LoginUserVo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.concurrent.TimeUnit;

/**
 * 过滤器，springmvc拦截器，aop通知切到controller，controller，异常处理执行顺序，
 * 外加springmvc流程控制：处理器映射器和处理器适配器
 * @author mayujing
 * @version 1.0
 */
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private JWTUtil jwtUtil;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //跨域请求浏览器默认发送一个预请求，先探测后台是否连通，如果预请求通就发送正式请求，预请求不携带token，正式才携带
        //但也走拦截器
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            return true;
        }
        //获取token的值
        // 从请求头中获取名为 "Authorization" 的值（前端应在此处携带令牌）
        String auth = request.getHeader("Authorization");
        if (StrUtil.isBlank(auth)||!auth.startsWith("Auth")){
            log.info("token不存在~");
            throw new BussinessException(ResultCode.TOKEN_NOTFOUND);
        }
        //substring(5) 表示截取从第 5 个字符开始的内容（去掉 "Auth" 前缀），得到纯令牌字符串
        String token = auth.substring(5);
        //2.解析token，获取登录用户的id
        String id = jwtUtil.extractId(token);
        if (StrUtil.isBlank(id)){
//        if ("".equals(id)) {
            //token不合法
            throw new BussinessException(ResultCode.TOKEN_NOTVALIDED);
        }
        //通过从redis中获取存储的json字符串，通过get(key)方法从 Redis 中查询该 key 对应的value。
        String userVoStr = (String) redisTemplate.opsForValue().get(Constant.TOKEN_PREFIX + id);
        //将JSON字符串反序列化为LoginUserVo对象
        LoginUserVo loginUserVo = JSONUtil.toBean(userVoStr, LoginUserVo.class);
        if (loginUserVo==null||!token.equals(loginUserVo.getToken())) {
            throw new BussinessException(ResultCode.TOKEN_EXPIRE);
        }

        //判断token是否需要续期
        //redis中获取剩余时间
        Long expire = redisTemplate.getExpire(Constant.TOKEN_PREFIX + id, TimeUnit.SECONDS);
        //如果剩余时间小于10分钟进行续期
        if (expire < Constant.TOKEN_REMAINING) {
            //续期
            redisTemplate.expire(Constant.TOKEN_PREFIX + id, Constant.TOKEN_TIME, TimeUnit.SECONDS);
        }
        //把当前登录的用户放到request中，后续使用
        request.setAttribute("loginUserVo",loginUserVo);
        return true;
    }
}
